#include <stdio.h>
#include <stdlib.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <net/if_arp.h>
#include <sys/timeb.h>
#include <time.h>
#include <pcap.h>
#include <string.h>
#include <unistd.h>

// 定义链表节点结构体
typedef struct dlist
{
    struct dlist *Last;                     // 上一个节点
    char *s_ip, *d_ip;                      // 两个ip地址
    uint8_t s_port, d_port;                 // 源端口和目的端口
    uint8_t proto;                          // 协议
    struct dlist *next;                     // 下一个节点
} dlist;

// 定义函数
dlist *creatDlist(char *s_ip, char *d_ip, uint8_t s_port, uint8_t d_port, uint8_t proto);
void dlistAdd(dlist *head, char *s_ip, char *d_ip, uint8_t s_port, uint8_t d_port, uint8_t proto);
void got_packet(unsigned char *args, const struct pcap_pkthdr *header, const unsigned char *packet);
void open_pcap(char *PAname, pcap_t **handle);
void set_filter(pcap_t *handle);
void loop_capture(pcap_t *handle, int num_packets, pcap_handler callback);

int main(int argc, char *argv[])
{
    char PAname[100];
    pcap_t *handle;

    if (argc != 2)
    {
        printf("Usage: ./a.out interface or \n./a.out filename.pcap\n");
        return -1;
    }

    strcpy(PAname, argv[1]);
    open_pcap(PAname, &handle);
    set_filter(handle);
    loop_capture(handle, -1, got_packet);

    pcap_close(handle);
    printf("\n Capture complete.\n");

    return 0;
}

// 具体函数实现
dlist *creatDlist(char *s_ip, char *d_ip, uint8_t s_port, uint8_t d_port, uint8_t proto)
{
    dlist *node = (dlist *)malloc(sizeof(dlist));
    node->s_ip = s_ip;
    node->d_ip = d_ip;
    node->s_port = s_port;
    node->d_port = d_port;
    node->proto = proto;
    node->Last = NULL;
    node->next = NULL;
    return node;
}

void dlistAdd(dlist *head, char *s_ip, char *d_ip, uint8_t s_port, uint8_t d_port, uint8_t proto)
{
    dlist *new_node = creatDlist(s_ip, d_ip, s_port, d_port, proto);

    if (head->d_ip == NULL)
    {
        head = new_node;
    }

    dlist *pt = head;
    while (pt->next != NULL)
        pt = pt->next;

    pt->next = new_node;
    new_node->Last = pt;
}

void got_packet(unsigned char *args, const struct pcap_pkthdr *header, const unsigned char *packet)
{
    // 对数据包进行解析
    char *s_ip = malloc(sizeof(char) * 16);
    char *d_ip = malloc(sizeof(char) * 16);
    sprintf(s_ip, "%d.%d.%d.%d", packet[26], packet[27], packet[28], packet[29]);
    sprintf(d_ip, "%d.%d.%d.%d", packet[30], packet[31], packet[32], packet[33]);
    uint8_t s_port = packet[34];
    uint8_t d_port = packet[36];
    uint8_t proto = packet[23];
    
    // 将解析结果存储到链表中
    dlistAdd(args, s_ip, d_ip, s_port, d_port, proto);
}

void open_pcap(char *PAname, pcap_t **handle)
{
    char errbuf[PCAP_ERRBUF_SIZE];

    if (access(PAname, 0) != -1)
    {
        *handle = pcap_open_offline(PAname, errbuf);
        if (*handle == NULL)
        {
            fprintf(stderr, "Could not open file %s: %s\n", PAname, errbuf);
            exit(EXIT_FAILURE);
        }
    }
    else
    {
        *handle = pcap_open_live(PAname, BUFSIZ, 1, 1000, errbuf);
        if (*handle == NULL)
        {
            printf("open live failed.\r\n");
            exit(EXIT_FAILURE);
        }
    }
}

void set_filter(pcap_t *handle)
{
    struct bpf_program fp;

    if (pcap_compile(handle, &fp, "", 0, PCAP_NETMASK_UNKNOWN) == -1)
    {
        fprintf(stderr, "Error compiling filter: %s\n", pcap_geterr(handle));
        exit(EXIT_FAILURE);
    }

    if (pcap_setfilter(handle, &fp) == -1)
    {
        fprintf(stderr, "Error setting filter: %s\n", pcap_geterr(handle));
        exit(EXIT_FAILURE);
    }
}

void loop_capture(pcap_t *handle, int num_packets, pcap_handler callback)
{
    if (pcap_loop(handle, num_packets, callback, NULL) < 0)
    {
        perror("pcap_loop error!\n");
        exit(EXIT_FAILURE);
    }
}
